using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace Terra.Core.Common.Models.Pagination;

/// <summary>
/// 分页列表实现
/// </summary>
/// <typeparam name="T">实体类型</typeparam>
public class PagedList<T> : IPagedList<T>
{
    /// <inheritdoc/>
    public int PageIndex { get; }

    /// <inheritdoc/>
    public int PageSize { get; }

    /// <inheritdoc/>
    public int TotalCount { get; }

    /// <inheritdoc/>
    public int TotalPages { get; }

    /// <inheritdoc/>
    public bool HasPreviousPage => PageIndex > 1;

    /// <inheritdoc/>
    public bool HasNextPage => PageIndex < TotalPages;

    /// <inheritdoc/>
    public IReadOnlyList<T> Items { get; }

    /// <inheritdoc/>
    public bool HasItems => Items.Any();

    /// <inheritdoc/>
    public int FirstItemIndex => (PageIndex - 1) * PageSize + 1;

    /// <inheritdoc/>
    public int LastItemIndex => Math.Min(PageIndex * PageSize, TotalCount);

    /// <inheritdoc/>
    public bool IsFirstPage => PageIndex == 1;

    /// <inheritdoc/>
    public bool IsLastPage => PageIndex == TotalPages;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="items">当前页数据</param>
    /// <param name="totalCount">总记录数</param>
    /// <param name="pageIndex">当前页码</param>
    /// <param name="pageSize">每页大小</param>
    public PagedList(IEnumerable<T> items, int totalCount, int pageIndex, int pageSize)
    {
        PageIndex = pageIndex;
        PageSize = pageSize;
        TotalCount = totalCount;
        TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize);
        Items = items.ToList().AsReadOnly();
    }

    /// <summary>
    /// 创建分页列表
    /// </summary>
    /// <param name="source">数据源</param>
    /// <param name="pageIndex">页码</param>
    /// <param name="pageSize">每页大小</param>
    /// <returns>分页列表</returns>
    public static PagedList<T> Create(IQueryable<T> source, int pageIndex, int pageSize)
    {
        var count = source.Count();
        var items = source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
        return new PagedList<T>(items, count, pageIndex, pageSize);
    }

    /// <summary>
    /// 异步创建分页列表
    /// </summary>
    /// <param name="source">数据源</param>
    /// <param name="pageIndex">页码</param>
    /// <param name="pageSize">每页大小</param>
    /// <returns>分页列表</returns>
    public static async Task<PagedList<T>> CreateAsync(IQueryable<T> source, int pageIndex, int pageSize)
    {
        var count = await source.CountAsync();
        var items = await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
        return new PagedList<T>(items, count, pageIndex, pageSize);
    }
}